package common

import (
	"fmt"
	"strconv"
	"strings"
	"time"
)

// 将int转time
const (
	// 定义每分钟的秒数
	SecondsPerMinute = 60
	// 定义每小时的秒数
	SecondsPerHour = SecondsPerMinute * 60
	// 定义每天的秒数
	SecondsPerDay = SecondsPerHour * 24
)

var (
	// DefaultDateTimeLayout 日期时间格式
	DefaultDateTimeLayout = "2006-01-02 15:04:05"
	// DefaultDateLayout 日期格式
	DefaultDateLayout = "2006-01-02"
)

// ResolveSeconds 将传入的“秒”解析为3种时间单位
func ResolveSeconds(seconds int) (s time.Duration) {
	return time.Duration(seconds) * time.Second
}

// SetExpiresIn 设置有效时间
func SetExpiresIn(seconds int, defSeconds int) (s time.Duration) {
	if seconds <= 0 {
		seconds = defSeconds
	}
	return ResolveSeconds(seconds)
}

//Date 设置时间(1524799394,"02/01/2006 15:04:05 PM")
func Date(format string, timestamp int64) string {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	if format == "" {
		format = "2006-01-02 15:04:05"
	}
	if timestamp == 0 {
		timestamp = time.Now().In(loc).Unix()
	}
	return time.Unix(timestamp, 0).In(loc).Format(format)
}

// ZeroTime 获取零点的时间戳
func ZeroTime(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
}

// SecToTime 将时分转成秒
func SecToTime(s int) string {
	var hour, minute string
	if s >= 24*60 {
		s = 24*60 - 1
	}
	if s <= 0 {
		s = 0
	}
	hour = fmt.Sprintf("%02d", s/60)
	minute = fmt.Sprintf("%02d", s%60)
	return hour + ":" + minute
}
func ResolveTime(seconds int64) (hour int64) {
	hour = seconds / SecondsPerHour
	return
}
func ResolveTimeFloat64(seconds float64) (hour float64) {
	hour = FriendlyFloat64(seconds / SecondsPerHour)
	return
}

// TimeToSec 将秒转时分 s格式
func TimeToSec(timeStr string) int {
	if timeStr == "" {
		return 0
	}
	s := strings.Split(timeStr, ":")
	var hour, minute int
	hour, _ = strconv.Atoi(s[0])
	if hour >= 24 {
		return 24*60 - 1
	}
	if hour < 0 {
		return 0
	}
	if len(s) > 1 {
		minute, _ = strconv.Atoi(s[1])
		if minute < 0 {
			minute = 0
		}
		if minute >= 60 {
			minute = 59
		}
	}
	return hour*60 + minute
}

// CurrentTimeToSec   当前时间转秒
func CurrentTimeToSec() int {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	currentTime := time.Now().In(loc)
	s := fmt.Sprintf("%d:%d", currentTime.Hour(), currentTime.Minute())
	return TimeToSec(s)
}

// DiffDays 两个时间戳相差天数
func DiffDays(t1, t2 int64) int {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	tStr1 := time.Unix(t1, 0).In(loc).Format(DefaultDateLayout)
	tStr2 := time.Unix(t2, 0).In(loc).Format(DefaultDateLayout)

	tm1, _ := time.ParseInLocation(DefaultDateLayout, tStr1, loc)
	tm2, _ := time.ParseInLocation(DefaultDateLayout, tStr2, loc)

	result := int(tm1.Sub(tm2).Hours() / 24)
	if result < 0 {
		result = -result
	}
	return result
}

// DiffSecond 两个时间戳相差秒数
func DiffSecond(t1, t2 int64) int64 {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	tStr1 := time.Unix(t1, 0).In(loc).Format(DefaultDateLayout)
	tStr2 := time.Unix(t2, 0).In(loc).Format(DefaultDateLayout)

	tm1, _ := time.ParseInLocation(DefaultDateLayout, tStr1, loc)
	tm2, _ := time.ParseInLocation(DefaultDateLayout, tStr2, loc)

	result := int64(tm1.Sub(tm2).Seconds())
	return result
}

// GetBetweenDate 通过两个时间戳获取日期数组
func GetBetweenDate(t1, t2 int64, layout ...string) []string {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	dates := make([]string, 0)
	if t1 == 0 || t2 == 0 {
		return dates
	}
	if t2 < t1 {
		// 如果结束时间小于开始时间，异常
		return dates
	}

	tm1 := time.Unix(t1, 0).In(loc)
	tm2 := time.Unix(t2, 0).In(loc)

	// 输出日期格式固定
	timeFormatTpl := DefaultDateLayout
	if len(layout) > 0 {
		timeFormatTpl = layout[0]
	}
	tStr1 := tm1.Format(timeFormatTpl)
	tStr2 := tm2.Format(timeFormatTpl)

	dates = append(dates, tStr1)

	if tStr1 == tStr2 {
		return dates
	}

	for {
		tm1 = tm1.AddDate(0, 0, 1)
		dateStr := tm1.Format(timeFormatTpl)
		dates = append(dates, dateStr)
		if dateStr == tStr2 {
			break
		}
	}
	return dates
}

// TimeRange 时间范围
type TimeRange struct {
	Start int64
	End   int64
}

// SplitTime 切割时间段
func SplitTime(t1, t2 int64, sec int64) (times []TimeRange) {
	times = make([]TimeRange, 0)
	if t1 == 0 || t2 == 0 || sec <= 0 {
		return
	}
	currentTime := time.Now().Unix()
	for {
		if t2 <= t1 || t1 > currentTime {
			break
		}
		tmp := t1 + sec
		if tmp > t2 {
			tmp = t2
		}
		times = append(times, TimeRange{t1, tmp})
		t1 = tmp
	}
	return
}

// StringToTime 字符串转时间
func StringToTime(day, t, format string) int64 {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	tt, _ := time.ParseInLocation(format, fmt.Sprintf("%s %s", day, t), loc)
	return tt.Unix()
}

// GetNowTime 当前时间
func GetNowTime() time.Time {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	return time.Now().In(loc)
}

// GetNowSecond 秒
func GetNowSecond() int64 {
	return GetNowTime().Unix()
}

// GetNowMillisecond 毫秒
func GetNowMillisecond() int64 {
	return GetNowTime().UnixNano() / 1e6
}

// DateToUnix 字符串转时间戳
func DateToUnix(date string, format ...string) int64 {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	f := "2006-01-02 15:04:05"
	if len(format) > 0 {
		f = format[0]
	}
	tt, _ := time.ParseInLocation(f, date, loc)
	return tt.Unix()
}

//UnixToDate 设置时间(1524799394,"02/01/2006 15:04:05 PM")
func UnixToDate(format string, timestamp int64) time.Time {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	if format == "" {
		format = "2006-01-02 15:04:05"
	}
	if timestamp == 0 {
		timestamp = time.Now().In(loc).Unix()
	}
	return time.Unix(timestamp, 0).In(loc)
}

// DateToMillisecond 字符串转毫秒
func DateToMillisecond(date string, format ...string) int64 {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	f := "2006-01-02 15:04:05"
	if len(format) > 0 {
		f = format[0]
	}
	tt, _ := time.ParseInLocation(f, date, loc)
	return tt.UnixNano() / 1e6
}

// ParseDate 字符串转时间对象
func ParseDate(date string, format ...string) (time.Time, error) {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	f := "2006-01-02 15:04:05"
	if len(format) > 0 {
		f = format[0]
	}
	return time.ParseInLocation(f, date, loc)
}

// SecWithTime 将时分转成秒
func SecWithTime(s int) string {
	if s >= 24*3600 {
		s = 24*3600 - 1
	}
	if s <= 0 {
		s = 0
	}
	var result string
	if s/3600 > 0 {
		result += fmt.Sprintf("%02d小时", s/3600)
	}
	if s%3600 > 0 {
		result += fmt.Sprintf("%02d分钟", s%3600/60)
	}
	return result
}

// TimeStrToStart 日期格式转换成整点
func TimeStrToStart(timeStr, format string) int64 {
	timeStamp := DateToUnix(timeStr, format)
	return TimeStampToStart(timeStamp)
}

// TimeStrToEnd 转换成结束的
func TimeStrToEnd(timeStr, format string) int64 {
	timeStamp := DateToUnix(timeStr, format)
	return TimeStampToEnd(timeStamp)
}

// TimeStampToHourStart 时间戳转小时开始时间戳
func TimeStampToHourStart(timestamp int64) int64 {
	if timestamp == 0 {
		return 0
	}
	tmpStr := time.Unix(timestamp, 0).Format("2006-01-02 15:00:00")
	startTimesStamp := DateToUnix(tmpStr, "2006-01-02 15:00:00")
	return startTimesStamp
}

// TimeStampToStart 将时间戳转换成今日整点时间戳
func TimeStampToStart(timestamp int64) int64 {
	if timestamp == 0 {
		return 0
	}
	tmpStr := time.Unix(timestamp, 0).Format("2006-01-02")
	startTimesStamp := DateToUnix(tmpStr, "2006-01-02")
	return startTimesStamp
}

// TimeStampToEnd 将时间戳转换为 xxxx 23:59:59这样的结束时间戳
func TimeStampToEnd(timestamp int64) int64 {
	if timestamp == 0 {
		return 0
	}
	startTimeStamp := TimeStampToStart(timestamp)
	return startTimeStamp + 86400 - 1
}

// DaysBeforeZeroTime N天前凌晨时间戳
func DaysBeforeZeroTime(days int64) int64 {
	currentZeroTime := ZeroTime(time.Now()).Unix()
	if days != 0 {
		return currentZeroTime - days*86400
	}
	return currentZeroTime
}

func FormateNewTime() time.Time {
	time1, _ := time.Parse(DefaultDateTimeLayout, FormateTime(time.Now()))
	return time1
}

func FormateNewTimeString() string {
	return FormateTime(time.Now())
}

func FormateTime(t time.Time) string {
	return t.Format(DefaultDateTimeLayout)
}

func FormateDate(t *time.Time) string {
	return t.Format(DefaultDateLayout)
}

func FormateDate2(t time.Time) string {
	return t.Format(DefaultDateLayout)
}

func FormateTime2(t time.Time) string {
	return t.Format(DefaultDateTimeLayout)
}

func GetAge(birthday int64) (age int) {
	if birthday == 0 {
		return
	}

	loc, _ := time.LoadLocation("Asia/Shanghai")
	tm1 := time.Unix(birthday, 0).In(loc)
	year := tm1.Year()
	if year <= 0 {
		age = -1
	}

	nowYear := time.Now().Year()
	age = nowYear - year
	return
}

func TimeByLocation(timeStr string) time.Time {
	local, _ := time.LoadLocation("Local")
	starttime, _ := time.ParseInLocation(DefaultDateTimeLayout, timeStr, local)
	return starttime
}
